# coding=utf-8
import random

from lib.CardSys.CardSys import CardSys
from lib.Character import ProfessionType
from lib.Skill import EffectType
from lib.Character.Armor import Armor
from lib.Character.Base import Base
from lib.Skill.Buff import Buff, BuffBase
from lib.Skill.Dot import Dot, DotBase
from lib.Character.Equipments import Equipments
from lib.Character.Profession import Profession
from lib.Core.Numerial import Numerial
from lib.Item.Equipment.Body import Body
from lib.Item.Equipment.Foot import Foot
from lib.Item.Equipment.Hand import Hand
from lib.Item.Equipment.Head import Head
from lib.Item.Equipment.Weapon import Weapon
from lib.Lang.character import *
from lib.Skill.Effect import Effect
from lib.Skill.Skill import Skill


class Character(object):
    def __init__(self, name, profession, race, base, up_base, level, skills=None, cards=None):
        super(Character, self).__init__()
        self.name = name
        self.level = level

        self.professio_id = profession
        self.professio = Profession(profession, base, up_base)
        self.race = race

        self.equipments = Equipments(Weapon(0), Head(0), Body(0), Foot(0), Hand(0))
        self.base = Base(self.professio.get_attributes_equipment(self.level, self.equipments))

        physical_armor = self.base_physical_armor(self.base) + self.equipments.physical_armor()
        magic_armor = self.base_magic_armor(self.base) + self.equipments.magic_armor()
        self.armor = Armor(physical_armor, magic_armor)

        self.attack = self.base_attack(self.base) + self.equipments.attack()
        self.attack_physical = self.base_attack_physical(self.base) + self.equipments.attack_physical()
        self.attack_magic = self.base_attack_magic(self.base) + self.equipments.attack_magic()
        self.defense = self.base_defense(self.base) + self.equipments.defense()
        self.defense_physical = self.base_defense_physical(self.base) + self.equipments.defense_physical()
        self.defense_magic = self.base_defense_magic(self.base) + self.equipments.defense_magic()

        self.speed = self.base_speed(self.base)
        maxhp = self.base_hp(self.base)
        self.hp = Numerial(maxhp, maxhp, 0)
        # self.hp.val = 1
        self.critical_point = 1.5

        self.turn_tick = 0

        self.buff = []
        self.dot = []

        if cards is None:
            cards = []
        self.card_system = CardSys(cards)

        if skills is None:
            skills = []
        self.skills = skills
        self.counter_skill = Skill('反击', 0, [Effect('反击伤害', EffectType.PHYSICAL_DAMAGE)])

    def reset_base_float_val(self):
        changed_physical_armor_num = self.base_physical_armor(self.base) + self.equipments.physical_armor()
        offest_physical_armor = changed_physical_armor_num - self.armor.physical_armor.max_val
        self.armor.physical_armor.max_val = changed_physical_armor_num
        if offest_physical_armor > 0:
            self.armor.physical_armor.increase(offest_physical_armor)
        else:
            self.armor.physical_armor.reduce(-offest_physical_armor)

        changed_max_magic_armor_num = self.base_magic_armor(self.base) + self.equipments.magic_armor()
        offest_maigc_armor = changed_max_magic_armor_num - self.armor.magic_armor.max_val
        self.armor.magic_armor.max_val = changed_max_magic_armor_num
        if offest_maigc_armor > 0:
            self.armor.magic_armor.increase(offest_maigc_armor)
        else:
            self.armor.magic_armor.reduce(-offest_maigc_armor)

        max_hp = self.base_hp(self.base)
        offset_hp = max_hp - self.hp.max_val
        self.hp.max_val = max_hp
        if offset_hp > 0:
            self.hp.increase(offset_hp)
        else:
            self.hp.reduce(-offset_hp)
            if self.hp.get_val() <= 0:
                self.hp.val = 1

        self.attack = self.base_attack(self.base) + self.equipments.attack()
        self.attack_physical = self.base_attack_physical(self.base) + self.equipments.attack_physical()
        self.attack_magic = self.base_attack_magic(self.base) + self.equipments.attack_magic()
        self.defense = self.base_defense(self.base) + self.equipments.defense()
        self.defense_physical = self.base_defense_physical(self.base) + self.equipments.defense_physical()
        self.defense_magic = self.base_defense_magic(self.base) + self.equipments.defense_magic()
        self.speed = self.base_speed(self.base)

    def select_skill(self, skills):
        if skills:
            return random.sample(skills, 1)[0]

    def turn_skills(self):
        skills = []
        for skill in self.skills:
            if skill.is_cd:
                skill.reduce_cd()
            else:
                skills.append(skill)
        return skills

    def turn_skill(self, targets_enemys, targets_friends, skill, scene_buf=None):
        skill.is_cd = True
        skill.reduce_cd()
        if scene_buf is None:
            scene_buf = []

        for effect in skill.effects:
            if effect.target_self:
                targets_enemys = targets_friends = [self]
            # 真实伤害
            if effect.effect_type == EffectType.DAMAGE:
                self.atk(targets_enemys, effect)
                # 反击
                self.counter(targets_enemys, targets_friends)
                # 连击
                self.combo(targets_enemys, targets_friends, skill)
            # 物理伤害
            elif effect.effect_type == EffectType.PHYSICAL_DAMAGE:
                self.physical_atk(targets_enemys, effect)
                # 反击
                self.counter(targets_enemys, targets_friends)
                # 连击
                self.combo(targets_enemys, targets_friends, skill)
            # 魔法伤害
            elif effect.effect_type == EffectType.MAGIC_DAMAGE:
                self.magic_atk(targets_enemys, effect)
            # 治疗
            elif effect.effect_type == EffectType.HEAL:
                self.heal(targets_friends, effect)
            # 回复物理护甲
            elif effect.effect_type == EffectType.PHYSICAL_ARMOR:
                self.heal_physical_armor(targets_friends, effect)
            # 回复魔法护甲
            elif effect.effect_type == EffectType.MAGIC_ARMOR:
                self.heal_magic_armor(targets_friends, effect)
            # 增强
            elif effect.is_buff():
                for char in targets_friends:
                    char.add_buff(effect)
            # 削弱
            elif effect.is_dot():
                for char in targets_enemys:
                    char.add_dot(effect)
            # 场景
            elif effect.is_scene():
                scene_buf.add_buff(targets_enemys, effect)
            else:
                print('error')

    def base_attack_physical(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 1
        else:
            offset = 0
        return int(base.strengt * offset)

    def base_attack_magic(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 1
        else:
            offset = 0
        return int(base.intellect * offset)

    def base_attack(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 1
        else:
            offset = 0
        return int(base.strengt * offset)

    def base_hp(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 500
        else:
            offset = 0
        return int(base.stamina * offset)

    def base_defense(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 0.3
        else:
            offset = 0
        return int(base.stamina * 0.4 + base.strengt * offset)

    def base_defense_physical(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 0.3
        else:
            offset = 0
        return int(base.stamina * 0.4 + base.strengt * offset)

    def base_defense_magic(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 0.3
        else:
            offset = 0
        return int(base.intellect * 0.4 + base.strengt * offset)

    def base_speed(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 0.5
        else:
            offset = 0

        return int(base.agility * offset)

    def base_physical_armor(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 8.5
        else:
            offset = 0

        return int(base.strengt * offset + base.stamina * 0.5)

    def base_magic_armor(self, base):
        if self.professio_id == ProfessionType.WARRIOR:
            offset = 0.2
        else:
            offset = 0

        return int(base.intellect * offset + base.stamina * 0.5)

    def is_dead(self, action=True):
        if self.hp.is_min_val():
            if action:
                self.dead_action()
            return True
        else:
            return False

    def dead_action(self):
        print(DEAD.format(self.name))

    # 真实攻击
    def atk(self, chars, effect):
        for char in chars:
            if char.is_dodge():
                break

            if char.is_dead(False) or self.is_dead(False):
                break

            # 目标 buff 减伤
            targe_offset_defense = 0
            for buff in char.has_offset_damage():
                targe_offset_defense += buff.offset_val
            # 自身 buff 增伤
            self_offset_act = 0
            for buff in self.has_damage():
                self_offset_act += buff.offset_val
            # 目标 dot 增伤
            target_easily_act = 0
            for dot in char.has_easily_damage():
                target_easily_act += dot.offset_val
            # 技能效果
            attack = self.attack + effect.offset_val
            # 总攻击
            act = attack + target_easily_act + self_offset_act - targe_offset_defense
            # 判断 暴击
            if self.is_critical():
                act = int(act * self.critical_point)
            if act < 0:
                act = 1
            char.hp.reduce(act)
            print(TRUE_DAMAGE.format(self.name, effect.name, char.name, act))
            print(TARGET_ARMOR.format(char.name, char.armor.physical_armor.get_val(), char.armor.magic_armor.get_val()))
            print(TARGET_HP.format(self.name, self.hp.get_val(), char.name, char.hp.get_val()))

    # 物理攻击
    def physical_atk(self, chars, effect):
        for char in chars:
            if char.is_dodge():
                break
            if char.is_dead(False) or self.is_dead(False):
                break

            # 目标 buff 减伤
            targe_offset_defense = 0
            for buff in char.has_offset_damage_physical():
                targe_offset_defense += buff.offset_val
            # 自身 buff 增伤
            self_offset_act = 0
            for buff in self.has_damage_physical():
                self_offset_act += buff.offset_val
            # 目标 dot 增伤
            target_easily_act = 0
            for dot in char.has_easily_damage_physical():
                target_easily_act += dot.offset_val
            # 技能效果
            attack = self.attack + effect.offset_val
            # 总攻击
            act = attack + target_easily_act + self_offset_act - targe_offset_defense
            # 判断 暴击
            if self.is_critical():
                act = int(act * self.critical_point)
            if act < 0:
                act = 1
            verity_overstep = char.armor.physical_armor.verity_overstep(act)
            if verity_overstep:
                overstep = char.armor.physical_armor.reduce_overstep(act)
                if overstep > 0:
                    armor = char.armor.physical_armor.get_val()
                    if armor > 0:
                        char.armor.physical_armor.reduce(armor)
                        print(DESTORY_PHYSIVAL_ARMOR.format(effect.name, char.name, armor))
                    char.hp.reduce(overstep)
                    print(TARGET_PHYSICAL_DAMAGE.format(effect.name, char.name, overstep))
                else:
                    char.hp.reduce(act)
                    print(DAMAGE_PHYSICAL.format(effect.name, char.name, act))
            else:
                char.armor.physical_armor.reduce(act)
                print(DAMAGE_PHYSICAL_ARMOR.format(effect.name, char.name, act))
            print(TARGET_ARMOR.format(char.name, char.armor.physical_armor.get_val(), char.armor.magic_armor.get_val()))
            print(TARGET_HP.format(self.name, self.hp.get_val(), char.name, char.hp.get_val()))

    # 魔法攻击
    def magic_atk(self, chars, effect):
        for char in chars:
            if char.is_dead(False) or self.is_dead(False):
                break
            # 目标 buff 减伤
            targe_offset_defense = 0
            for buff in char.has_offset_damage_magic():
                targe_offset_defense += buff.offset_val
            # 自身 buff 增伤
            self_offset_act = 0
            for buff in self.has_damage_magic():
                self_offset_act += buff.offset_val
            # 目标 dot 增伤
            target_easily_act = 0
            for dot in char.has_easily_damage_magic():
                target_easily_act += dot.offset_val
            # 技能效果
            attack = self.attack + effect.offset_val
            # 总攻击
            act = attack + target_easily_act + self_offset_act - targe_offset_defense
            # 判断 暴击
            if self.is_critical():
                act = int(act * self.critical_point)
            if act < 0:
                act = 0
            verity_overstep = char.armor.magic_armor.verity_overstep(act)
            if verity_overstep:
                overstep = char.armor.magic_armor.reduce_overstep(act)
                if overstep > 0:
                    armor = char.armor.magic_armor.get_val()
                    if armor > 0:
                        char.armor.magic_armor.reduce(armor)
                        print(DESTORY_MAGIC_ARMOR.format(effect.name, char.name, armor))
                    char.hp.reduce(overstep)
                    print(TARGET_MAGIC_DAMAGE.format(effect.name, char.name, overstep))
                else:
                    char.hp.reduce(act)
                    print(DAMAGE_MAGIC.format(effect.name, char.name, act))
            else:
                char.armor.magic_armor.reduce(act)
                print(DAMAGE_MAGIC_ARMOR.format(effect.name, char.name, act))
            print(TARGET_ARMOR.format(char.name, char.armor.magic_armor.get_val(), char.armor.magic_armor.get_val()))
            print(TARGET_HP.format(self.name, self.hp.get_val(), char.name, char.hp.get_val()))

    # 治疗
    def heal(self, chars, effect):
        for char in chars:
            if char.is_dead(False) or self.is_dead(False):
                break
            # 增量治疗
            offset_heal = 0
            for buff in char.has_offset_heal():
                offset_heal += buff.offset_val
            # 抑制治疗
            easily_heal = 0
            for dot in char.has_easily_heal():
                easily_heal += dot.offset_val

            heal = self.attack + effect.offset_val + offset_heal - easily_heal
            # 判断 暴击
            if self.is_critical():
                heal = int(heal * self.critical_point)
            char.hp.increase(heal)
            print(
                TARGET_HEAL.format(self.name, effect.name, char.name, heal, self.attack + effect.offset_val,
                                   offset_heal, easily_heal))

    # 补充物理护甲
    def heal_physical_armor(self, chars, effect):
        for char in chars:
            heal = self.attack + effect.offset_val
            char.armor.physical_armor.increase(heal)
            print(HEAL_PHYSICAL_ARMOR.format(self.name, effect.name, char.name, heal))
            print(TARGET_ARMOR.format(char.name, char.armor.physical_armor.get_val(), char.armor.magic_armor.get_val()))
            print(TARGET_HP.format(self.name, self.hp.get_val(), char.name, char.hp.get_val()))

    # 补充魔法护甲
    def heal_magic_armor(self, chars, effect):
        for char in chars:
            heal = self.attack + effect.offset_val
            char.armor.magic_armor.increase(heal)
            print(HEAL_MAGIC_ARMOR.format(self.name, effect.name, char.name, heal))
            print(TARGET_ARMOR.format(char.name, char.armor.physical_armor.get_val(), char.armor.magic_armor.get_val()))
            print(TARGET_HP.format(self.name, self.hp.get_val(), char.name, char.hp.get_val()))

    def over_buff_round(self):
        pass

    def add_buff(self, buff):
        if buff.effect_type is EffectType.BUFF_BASE:
            buff = BuffBase(buff.name, buff.round, buff.base, buff.target_self)
        else:
            buff = Buff(buff.name, buff.effect_type, buff.round, buff.target_self)
        # if len(self.buff) <= 0:
        self.buff.append(buff)
        print(ADD_BUFF.format(self.name, buff.name)) + ' : ' + str(buff.offset_val)

    def add_dot(self, dot):
        if dot.effect_type is EffectType.DOT_BASE:
            dot = DotBase(dot.name, dot.round, dot.base, dot.target_self)
        else:
            dot = Dot(dot.name, dot.effect_type, dot.round, dot.target_self)
        self.dot.append(dot)
        print(ADD_DOT.format(self.name, dot.name)) + ' : ' + str(dot.offset_val)

    def effect_buff(self):
        if self.buff and self.is_dead(False):
            for buff in self.buff:
                # 每回合执行
                if buff.effect_type is EffectType.BUFF_HEAL:
                    buff_heal = buff.offset_val
                    offset_heal = 0
                    for buff in self.has_offset_heal():
                        offset_heal += buff.offset_val
                    easily_heal = 0
                    for dot in self.has_easily_heal():
                        easily_heal = + dot.offset_val
                    val = buff_heal + offset_heal - easily_heal
                    print BUFF_HEAL.format(self.name, val, buff_heal, offset_heal, easily_heal)
                    self.hp.increase(val)
                elif buff.effect_type is EffectType.BUFF_HEAL_PHYSICAL_ARMOR:
                    val = buff.offset_val
                    self.armor.physical_armor.increase(val)
                    print '{3} :{0} 回复了 {1} 物理护甲，round {2}'.format(buff.name, val, buff.round, self.name)
                elif buff.effect_type is EffectType.BUFF_HEAL_MAGIC_ARMOR:
                    val = buff.offset_val
                    self.armor.magic_armor.increase(val)
                    print '{3} :{0} 回复了 {1} 魔法护甲，round {2}'.format(buff.name, val, buff.round, self.name)
                elif buff.effect_type is EffectType.BUFF_VERTIGO:
                    print '{0}免疫眩晕:{1}'.format(self.name, buff.round)
                elif buff.effect_type is EffectType.BUFF_MOVE:
                    print '{0}免疫移动限制:{1}'.format(self.name, buff.round)
                # 属性增强
                if buff.round == buff.max_round and buff.effect_type is EffectType.BUFF_BASE:
                    data = {
                        'stamina': self.base.stamina + buff.base.stamina,
                        'strengt': self.base.strengt + buff.base.strengt,
                        'agility': self.base.agility + buff.base.agility,
                        'intellect': self.base.intellect + buff.base.intellect,
                        'dodge': self.base.dodge + buff.base.dodge,
                        'combo': self.base.combo + buff.base.combo,
                        'critical': self.base.critical + buff.base.critical,
                        'counter': self.base.counter + buff.base.counter
                    }
                    self.base = Base(data)
                    self.reset_base_float_val()
                if buff.round < 0 and buff.effect_type is EffectType.BUFF_BASE:
                    data = {
                        'stamina': self.base.stamina - buff.base.stamina,
                        'strengt': self.base.strengt - buff.base.strengt,
                        'agility': self.base.agility - buff.base.agility,
                        'intellect': self.base.intellect - buff.base.intellect,
                        'dodge': self.base.dodge - buff.base.dodge,
                        'combo': self.base.combo - buff.base.combo,
                        'critical': self.base.critical - buff.base.critical,
                        'counter': self.base.counter - buff.base.counter
                    }
                    self.base = Base(data)
                    self.reset_base_float_val()
                # 持续时间
                if buff.round < 0:
                    self.buff.remove(buff)

    def effect_dot(self):
        if self.dot:
            for dot in self.dot:
                if dot.effect_type is EffectType.DOT_DAMAGE:
                    dot_act = dot.offset_val
                    offset_defense = 0
                    for buff in self.has_offset_damage():
                        offset_defense += buff.offset_val
                    easily_act = 0
                    for dot in self.has_easily_damage():
                        easily_act += dot.offset_val
                    val = dot_act + easily_act - offset_defense
                    self.hp.reduce(val)
                    print '流血{0}(基础:{1};增伤{2};抵抗{3})'.format(val, dot_act, easily_act, offset_defense)
                if dot.effect_type is EffectType.DOT_DAMAGE_PHYSICAL:
                    offset_defense = 0
                    for buff in self.has_offset_damage_physical():
                        offset_defense += buff.offset_val
                    easily_act = 0
                    for dot in self.has_easily_damage_physical():
                        easily_act += dot.offset_val
                    val = dot.offset_val + easily_act - offset_defense
                    offset = val - self.armor.physical_armor.get_val()
                    if offset > 0:
                        self.armor.physical_armor.reduce(self.armor.physical_armor.get_val())
                        self.hp.reduce(offset)
                    else:
                        self.armor.physical_armor.reduce(val)
                if dot.effect_type is EffectType.DOT_DAMAGE_MAGIC:
                    offset_defense = 0
                    for buff in self.has_offset_damage_magic():
                        offset_defense += buff.offset_val
                    easily_act = 0
                    for dot in self.has_easily_damage_magic():
                        easily_act += dot.offset_val
                    val = dot.offset_val + easily_act - offset_defense
                    offset = val - self.armor.magic_armor.get_val()
                    if offset > 0:
                        self.armor.magic_armor.reduce(self.armor.magic_armor.get_val())
                        self.hp.reduce(offset)
                    else:
                        self.armor.magic_armor.reduce(val)
                # 属性削弱
                if dot.round == dot.max_round and dot.effect_type is EffectType.DOT_BASE:
                    data = {
                        'stamina': self.base.stamina - buff.base.stamina,
                        'strengt': self.base.strengt - buff.base.strengt,
                        'agility': self.base.agility - buff.base.agility,
                        'intellect': self.base.intellect - buff.base.intellect,
                        'dodge': self.base.dodge - buff.base.dodge,
                        'combo': self.base.combo - buff.base.combo,
                        'critical': self.base.critical - buff.base.critical,
                        'counter': self.base.counter - buff.base.counter
                    }
                    self.base = Base(data)
                    self.reset_base_float_val()
                if dot.round < 0 and dot.effect_type is EffectType.DOT_BASE:
                    data = {
                        'stamina': self.base.stamina + buff.base.stamina,
                        'strengt': self.base.strengt + buff.base.strengt,
                        'agility': self.base.agility + buff.base.agility,
                        'intellect': self.base.intellect + buff.base.intellect,
                        'dodge': self.base.dodge + buff.base.dodge,
                        'combo': self.base.combo + buff.base.combo,
                        'critical': self.base.critical + buff.base.critical,
                        'counter': self.base.counter + buff.base.counter
                    }
                    self.base = Base(data)
                    self.reset_base_float_val()
                if dot.round < 0:
                    self.buff.remove(dot)

    def has_vertigo_buff(self):
        for buff in self.buff:
            if buff.effect_type is EffectType.BUFF_VERTIGO:
                return True
        return False

    def has_move_buff(self):
        for buff in self.buff:
            if buff.effect_type is EffectType.BUFF_MOVE:
                return True
        return False

    def has_offset_damage(self):
        list = []
        for effect in self.buff:
            if effect.effect_type is EffectType.BUFF_OFFSET_DAMAGE:
                list.append(effect)
        return list

    def has_offset_damage_physical(self):
        list = []
        for effect in self.buff:
            if effect.effect_type is EffectType.BUFF_OFFSET_PHYSICAL_DAMAGE:
                list.append(effect)
        return list

    def has_offset_damage_magic(self):
        list = []
        for effect in self.buff:
            if effect.effect_type is EffectType.BUFF_OFFSET_MAGIC_DAMAGE:
                list.append(effect)
        return list

    def has_offset_heal(self):
        list = []
        for effect in self.buff:
            if effect.effect_type is EffectType.BUFF_OFFSET_HEAL:
                list.append(effect)
        return list

    def has_easily_damage(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.DOT_EASILY_DAMAGE:
                list.append(effect)
        return list

    def has_easily_damage_physical(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.DOT_EASILY_PHYSICAL_DAMAGE:
                list.append(effect)
        return list

    def has_easily_damage_magic(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.DOT_EASILY_MAGIC_DAMAGE:
                list.append(effect)
        return list

    def has_easily_heal(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.DOT_HEAL:
                list.append(effect)
        return list

    def has_damage(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.BUFF_DAMAGE:
                list.append(effect)
        return list

    def has_damage_physical(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.BUFF_DAMAGE_PHYSICAL:
                list.append(effect)
        return list

    def has_damage_magic(self):
        list = []
        for effect in self.dot:
            if effect.effect_type is EffectType.BUFF_DAMAGE_MAGIC:
                list.append(effect)
        return list

    def has_vertigo_dot(self):
        for effect in self.dot:
            if effect.effect_type is EffectType.DOT_VERTIGO:
                return True
        return False

    # 反击
    def counter(self, target_enemy, target_friends):
        for char in target_enemy:
            if not char.is_dead(False) and not self.is_dead(False):
                if char.is_counter():
                    skill = char.counter_skill
                    target_enemys = [self]
                    target_friends = target_friends
                    char.turn_skill(target_enemys, target_friends, skill)
                    break
                else:
                    break
            else:
                break

    # 连击
    def combo(self, targets_enemys, targets_friends, skill):
        for char in targets_enemys:
            if char.is_dead(False) or self.is_dead(False):
                break
            else:
                while self.is_combo():
                    for effect in skill.effects:
                        # 过滤掉 非物理 和 真实伤害技能
                        effects = []
                        if effect.effect_type is EffectType.PHYSICAL_DAMAGE or effect.effect_type is EffectType.DAMAGE:
                            effects.append(effect)
                        skill = Skill(skill.name, skill.cd, effects)
                    self.turn_skill(targets_enemys, targets_friends, skill)
                    break

    # 判断 连击
    def is_combo(self):
        combo_point = self.base.combo
        combo_rand_int = random.randint(1, 100)
        if combo_point >= combo_rand_int:
            print('{0} 连击!'.format(self.name))
            return True
        return False

    # 判断 反击
    def is_counter(self):
        counter_point = self.base.counter
        counter_rand_int = random.randint(1, 100)
        if counter_point >= counter_rand_int:
            print('{0} 反击！'.format(self.name))
            return True
        return False

    # 判断 暴击
    def is_critical(self):
        critical_point = self.base.critical
        critical_rand_int = random.randint(1, 100)
        if critical_point >= critical_rand_int:
            print('{0} 暴击！'.format(self.name))
            return True
        return False

    # 判断闪避
    def is_dodge(self):
        dodge_point = self.base.dodge
        dodge_rand_int = random.randint(1, 100)
        if dodge_point >= dodge_rand_int:
            print('{0} 闪避！'.format(self.name))
            return True
        return False
